/**
 * @Author:Geln Yang
 * @Created:2008-8-10
 * $ Revision: 1.0 $
 * $ Author: Geln Yang $
 * $ Date: 2008-8-10 $
 */
package org.geln.web.junit;

import java.sql.DriverManager;

import junit.framework.TestCase;

import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * @Author:Geln Yang
 * @Created:2008-8-10
 */
public abstract class AbstractBaseTestCase extends TestCase {
	
	private static final ThreadLocal sessions = new ThreadLocal();

	protected ApplicationContext context;
	
	protected void setUp() throws Exception {
		context = new ClassPathXmlApplicationContext(getContextPath());
		IDatabaseConnection connection = null;
		try{
			connection = getConnection();
			DatabaseOperation.CLEAN_INSERT.execute(connection, getDataSet());
		}finally{
			if(connection!=null){
				try {
					connection.close();
				} catch (Exception e) {
				}
			}
		}
		openSession();		
	}

	protected void tearDown() throws Exception {
		closeSession();
		((ClassPathXmlApplicationContext) context).close();
		super.tearDown();
	}

	private void openSession() {
		SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
		Session hibSession = SessionFactoryUtils.getSession(sessionFactory, true);
		hibSession.setFlushMode(FlushMode.AUTO);
		TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(hibSession));
	}

	protected void closeSession() {
		SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
				.unbindResource(sessionFactory);
		SessionFactoryUtils.releaseSession(sessionHolder.getSession(), sessionFactory);
	}

	protected Session getSession() {
		Session session = (Session) sessions.get();
		if (null == session) {
			SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
			session = sessionFactory.openSession();
			sessions.set(session);
		}
		return session;
	}

	protected IDatabaseConnection getConnection() throws Exception {
		Class.forName(getDriverClass());
		if(getSchema()!=null && getSchema().trim().length()>0){
			return new DatabaseConnection(DriverManager.getConnection(getUrl(), getUser(), getPassword()),getSchema());
		}
		else{
			return new DatabaseConnection(DriverManager.getConnection(getUrl(), getUser(), getPassword()));
		}
	}

	protected IDataSet getDataSet() throws Exception {
		return new FlatXmlDataSet(AbstractBaseTestCase.class.getClassLoader().getResourceAsStream(getXMLResource()));
	}

	protected abstract String[] getContextPath();

	protected abstract String getXMLResource();
	
	protected abstract String getDriverClass();
	
	protected abstract String getUrl();
	
	protected abstract String getUser();
	
	protected abstract String getPassword();
	
	protected abstract String getSchema();
}
